package utils;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import constants.Configurations;
import play.Logger;
import play.libs.Codec;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;


public class SignUtil {

    /**
     * 生成签名
     *
     * @param params
     * @return
     */
    public static String generateSign(Map<String, Object> params,String caller,String secretKey) {
        String sign=getMD5Sign(caller,secretKey,params);
        return  sign;
    }

    public static String getMD5Sign(String caller, String secretKey, Map<String, Object> dataMap) {
        // 把 Map 转为 JsonObject
        JsonObject data = new JsonParser().parse(new Gson().toJson(dataMap)).getAsJsonObject();

        // 得到排序后的map，并将key和value之间用等号连接
        String sortedDataStr = "";
        List<String> keys = new ArrayList<String>();
        //for (Map.Entry<String, Object> entry : data.entrySet()) {
        for (Map.Entry<String, JsonElement> entry : data.entrySet()) {
            // 如要忽略jsonarray，jsonobject类型的判断，则要进行 isJsonPrimitive 判断
            //if (entry.getValue().isJsonPrimitive()) {
            keys.add(entry.getKey());
            //}
        }
        if (keys.size() > 0) {
            Collections.sort(keys);
            for (String key : keys) {
                if (data.get(key).isJsonPrimitive()) {
                    sortedDataStr += key + data.get(key).getAsString();
                } else if (data.get(key).isJsonArray()) {
                    sortedDataStr += key + data.get(key).getAsJsonArray().toString();
                } else if (data.get(key).isJsonObject()) {
                    sortedDataStr += key + data.get(key).getAsJsonObject().toString();
                }
            }
        }
        // 签名算法：md5(caller + sorted_compact_data + secret_key)
        return Codec.hexMD5(caller + sortedDataStr + secretKey);
    }


    public static boolean checkSignature(String token, String signature, String timestamp, String nonce){
        String[] arr = new String[]{token, timestamp, nonce};
        // 将 token, timestamp, nonce 三个参数进行字典排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for(int i = 0; i < arr.length; i++){
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行 shal 加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        content = null;
        // 将sha1加密后的字符串可与signature对比，标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param digest
     * @return
     */
    private static String byteToStr(byte[] digest) {
        // TODO Auto-generated method stub
        String strDigest = "";
        for(int i = 0; i < digest.length; i++){
            strDigest += byteToHexStr(digest[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     * @param b
     * @return
     */
    private static String byteToHexStr(byte b) {
        // TODO Auto-generated method stub
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(b >>> 4) & 0X0F];
        tempArr[1] = Digit[b & 0X0F];

        String s = new String(tempArr);
        return s;
    }

    /**
     * create_nonce_str
     * @return
     */
    public static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    /**
     * create_timestamp
     * @return
     */
    public static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    /**
     * byteToHex
     * @param hash
     * @return
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * getSignature
     * @param string1
     * @return
     */
    public static String getSignature(String string1) {
        String signature = "";
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return signature;
    }
}
